package LeetCode刷题.之前的算法;

import java.util.Scanner;

public class sameAncestor {
    public static void main(String arg[]) {
        TreeNode t=new TreeNode();
        t=createTree(t);

    }
    private static class TreeNode {
        TreeNode left, right;
        String val;
    }
    private static TreeNode createTree(TreeNode T) {
        if (T != null) {
            Scanner scanner = new Scanner(System.in);
            String point;
            System.out.print("请输入节点的名称(”#“代表空节点)：");
            T = new TreeNode();
            point = scanner.nextLine();
            if (point.equals("#")) {
                T = null;
            } else {
                T.val = point;
                T.left = createTree(T.left);
                T.right = createTree(T.right);
            }
        }
        return T;
    }
    //二叉树的最近公共祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) {//如果根节点为null则返回root；如果根节点为p或者q，则满足最近公共结点为其中一个节点的要求，同样返回root
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q);// 递归遍历左子树，只要在左子树中找到了p或q，则先找到谁就返回谁
        TreeNode right = lowestCommonAncestor(root.right, p, q);// 递归遍历右子树，只要在右子树中找到了p或q，则先找到谁就返回谁
        if (left == null) {// 如果在左子树中 p和 q都找不到，则 p和 q一定都在右子树中，右子树中先遍历到的那个就是最近公共祖先（一个节点也可以是它自己的祖先）
            return right;
        }
        if (right == null) {
            // 否则，如果 left不为空，在左子树中有找到节点（p或q），这时候要再判断一下右子树中的情况，
            // 如果在右子树中，p和q都找不到，则 p和q一定都在左子树中，左子树中先遍历到的那个就是最近公共祖先（一个节点也可以是它自己的祖先）
            return left;
        }
        return root;
    }
//    一、 终止条件：
//    当越过叶节点，则直接返回 null ；
//    当 root 等于 p,q ，则直接返回 root ；

//    二、 递推工作：
//    开启递归左子节点，返回值记为 left ；
//    开启递归右子节点，返回值记为 right ；

//    三、 返回值： 根据 left 和 right ，可展开为四种情况；********
//    当 left 和 right 同时为空 ：说明 root 的左 / 右子树中都不包含 p,q ，返回 null ；
//    当 left 和 right 同时不为空 ：说明 p,q 分列在 root 的 异侧 （分别在 左 / 右子树），因此 root 为最近公共祖先，返回 root ；
//    当 left 为空 right 不为空 ：p,q 都不在 root 的左子树中，直接返回 right 。
//
//    具体可分为两种情况：
//   《1》 p,q 其中一个在 root 的 右子树 中，此时 right 指向 p（假设为 p ）；
//   《2》 p,q 两节点都在 root 的 右子树 中，此时的 right 指向 最近公共祖先节点 ；
//    当 left 不为空 ， right 为空 ：与情况 3. 同理；
}
